﻿using GalaSoft.MvvmLight;
using System.Collections.ObjectModel;
using System;
using MovieGalleryDLL;
using GalaSoft.MvvmLight.Command;
using System.Diagnostics;
using System.Windows.Controls;
using System.Linq;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Collections.Generic;
using MovieGalleryDLL.Collections;
using System.Threading;

namespace MovieGallery.ViewModel
{
    /// <summary>
    /// This class contains properties that the main View can data bind to.
    /// </summary>
    public class MainViewModel : ViewModelBase
    {
        MoviesDB db;
        BackgroundWorker backgroundWorker;
        BackgroundWorker backgroundScanner;
        BackgroundWorker backgroundDatabaseWorker;
        Scanner scanner;

        public RelayCommand<string> MovieLeftButtonUpCommand
        {
            get;
            private set;
        }

        public SafeObservable<MovieTabList> Tabs
        {
            get;
            set;
        }

        public MovieTabList AllMoviesTab
        {
            get;
            set;
        }

        public List<string> FilePaths
        {
            get;
            set;
        }

        /// <summary>
        /// Initializes a new instance of the MainViewModel class.
        /// </summary>
        public MainViewModel()
        {
            if (!IsInDesignMode)
            {
                db = new MoviesDB();

                MovieLeftButtonUpCommand = new RelayCommand<string>((path) => MovieLeftButtonUpAction(path));

                Tabs = new SafeObservable<MovieTabList>();
                AllMoviesTab = new MovieTabList() { Header = "All" };

                Tabs.Add(AllMoviesTab);

                backgroundDatabaseWorker = new BackgroundWorker();
                backgroundDatabaseWorker.DoWork += new DoWorkEventHandler(backgroundDatabaseWorker_DoWork);
                backgroundDatabaseWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundDatabaseWorker_RunWorkerCompleted);

                backgroundWorker = new BackgroundWorker();
                backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
                backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);

                backgroundScanner = new BackgroundWorker();
                backgroundScanner.DoWork += new DoWorkEventHandler(backgroundScanner_DoWork);
                backgroundScanner.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundScanner_RunWorkerCompleted);
                backgroundScanner.RunWorkerAsync();
            }
        }

        void backgroundDatabaseWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            backgroundWorker.RunWorkerAsync();
        }

        void backgroundDatabaseWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            MoviesDB.AddMovies(FilePaths);
        }

        void backgroundScanner_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            backgroundDatabaseWorker.RunWorkerAsync();
        }

        void backgroundScanner_DoWork(object sender, DoWorkEventArgs e)
        {
            scanner = new Scanner();
            scanner.ScanCompleted += new Scanner.ScanCompletedEventHandler(scanner_ScanCompleted);
            scanner.StartScanning();
        }

        void scanner_ScanCompleted(List<string> filePaths)
        {
            FilePaths = filePaths;
        }

        private List<Movie> UpdateData()
        {
            return db.GetMovies();
        }

        private void SortToGenre()
        {
            foreach (Movie movie in AllMoviesTab)
            {
                MovieTabList tab = Tabs.DefaultIfEmpty(AllMoviesTab).FirstOrDefault(t => t.Header.Equals(movie.Genre));
                if (tab != null && !tab.Equals(AllMoviesTab))
                {
                    tab.Add(movie);
                }
                else
                {
                    Tabs.Add(new MovieTabList() { Header = movie.Genre });
                }
            }
        }

        private void MovieLeftButtonUpAction(string path)
        {
            Debug.WriteLine("Action: " + path);
        }

        // Worker Method
        void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            e.Result = UpdateData();
        }

        // Completed Method
        void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                // cancelled
            }
            else if (e.Error != null)
            {
                // exception thrown
            }
            else
            {
                foreach (Movie m in (List<Movie>)e.Result)
                {
                    AllMoviesTab.Add(m);

                    SortToGenre();
                }
            }
        }
    }
}